package com.imporven.sell.service.impl;

import com.imporven.sell.convert.OrderMaster2OrderDTOConvert;
import com.imporven.sell.domain.OrderDetail;
import com.imporven.sell.domain.OrderMaster;
import com.imporven.sell.domain.ProductInfo;
import com.imporven.sell.dto.CartDTO;
import com.imporven.sell.dto.OrderDTO;
import com.imporven.sell.enums.OrderStatusEnum;
import com.imporven.sell.enums.PayStatusEnum;
import com.imporven.sell.enums.ResultEnum;
import com.imporven.sell.exception.SellException;
import com.imporven.sell.repository.OrderDetailRepository;
import com.imporven.sell.repository.OrderMasterRepository;
import com.imporven.sell.repository.ProductInfoRepository;
import com.imporven.sell.service.OrderService;
import com.imporven.sell.service.ProductService;
import com.imporven.sell.util.IDGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author imporven
 * @version 1.0.0
 * @date 2018-7-15 1:29
 */
@Service
@Slf4j
public class OrderServiceImp implements OrderService {

    @Autowired
    private ProductInfoRepository productInfoRepository;
    @Autowired
    private OrderDetailRepository orderDetailRepository;
    @Autowired
    private OrderMasterRepository orderMasterRepository;
    @Autowired
    private ProductService productService;

    @Override
    @Transactional
    public OrderDTO create(OrderDTO orderDto) {

        String orderId = IDGenerator.generateID();
        BigDecimal orderAmount = new BigDecimal(0);
        //1. 查询商品（数量, 价格） 计算总价
        for (OrderDetail orderDetail: orderDto.getOrderDetailList()) {
            ProductInfo product = productInfoRepository.findById(orderDetail.getProductId())
                                    .orElseThrow(new SellException(ResultEnum.PRODUCT_NOT_EXIST));

            //计算总价
            orderAmount = product.getProductPrice()
                                .multiply(new BigDecimal(orderDetail.getProductNum()))
                                .add(orderAmount);

            //2.订单详情入库
            BeanUtils.copyProperties(product,orderDetail);
            orderDetail.setDetailId(IDGenerator.generateID());
            orderDetail.setOrderId(orderId);
            orderDetailRepository.save(orderDetail);
        }

        //3.订单入库
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDto,orderMaster);
        orderMaster.setOrderId(orderId);
        orderMaster.setOrderAmount(orderAmount);
        orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
        orderMasterRepository.save(orderMaster);

        //4.扣库存
        List<CartDTO> cartDTOList = orderDto.getOrderDetailList().stream()
                                    .map(orderDetail -> new CartDTO(orderDetail.getProductId(),orderDetail.getProductNum()))
                                    .collect(Collectors.toList());
        productService.decreaseStock(cartDTOList);

        BeanUtils.copyProperties(orderMaster,orderDto);
        return orderDto;
    }

    @Override
    public Page<OrderDTO> findList(String openid, Pageable pageable) {
        Page<OrderMaster> orderMasterPage = orderMasterRepository.findByBuyerOpenid(openid,pageable);

        List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConvert.convert(orderMasterPage.getContent());

        return new PageImpl<OrderDTO>(orderDTOList,pageable,orderMasterPage.getTotalElements());
    }

    @Override
    public Optional<OrderDTO> findOne(String orderId) {
        return Optional.ofNullable(orderMasterRepository.findById(orderId)
                                        .map(orderMaster -> {
                                            List<OrderDetail> orderDetails = orderDetailRepository.findByOrderId(orderId);
                                            OrderDTO orderDTO = new OrderDTO();
                                            BeanUtils.copyProperties(orderMaster, orderDTO);
                                            orderDTO.setOrderDetailList(orderDetails);
                                            return orderDTO;
                                        })
                                        .orElse(null));

    }
}
